from django_filters import rest_framework as filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
from django.db import transaction

from inventory.serializers import InventoryTransactionSerializer
from inventory.models import InventoryTransaction, TransactionType, Inventory
from utils.custom_model_viewSet import CustomModelViewSet


class InventoryTransactionFilter(filters.FilterSet):
    """
    库存交易记录过滤类，用于交易记录列表过滤
    """
    product_name = filters.CharFilter(field_name='product__name', lookup_expr='icontains')
    product_sku = filters.CharFilter(field_name='product__sku', lookup_expr='icontains')
    from_warehouse_name = filters.CharFilter(field_name='from_warehouse__warehouse_name', lookup_expr='icontains')
    to_warehouse_name = filters.CharFilter(field_name='to_warehouse__warehouse_name', lookup_expr='icontains')
    reference_document = filters.CharFilter(field_name='reference_document', lookup_expr='icontains')
    transaction_date_range = filters.DateFromToRangeFilter(field_name='create_time')
    
    class Meta:
        model = InventoryTransaction
        fields = [
            'transaction_id', 'transaction_type', 'product', 'from_warehouse', 
            'to_warehouse', 'from_location', 'to_location', 'quantity', 
            'reference_document', 'reference_type', 'lot_number', 'serial_number'
        ]


class InventoryTransactionViewSet(CustomModelViewSet):
    """
    库存交易记录视图集，提供交易记录的增删改查操作
    """
    queryset = InventoryTransaction.objects.filter(is_deleted=False).order_by('-create_time')
    serializer_class = InventoryTransactionSerializer
    filterset_class = InventoryTransactionFilter
    search_fields = [
        'product__name', 'product__sku', 'reference_document', 
        'lot_number', 'serial_number'
    ]
    ordering_fields = ['create_time', 'transaction_id', 'quantity']
    ordering = ['-create_time']
    enable_soft_delete = True
    
    @action(detail=False, methods=['post'], url_path='create-transaction')
    def create_transaction(self, request, *args, **kwargs):
        """
        创建库存交易并更新库存数量
        
        Args:
            request: HTTP请求对象，包含交易信息
        
        Returns:
            Response: 交易创建结果和更新后的库存信息
        """
        try:
            with transaction.atomic():
                # 1. 创建交易记录
                serializer = self.get_serializer(data=request.data)
                serializer.is_valid(raise_exception=True)
                transaction_obj = serializer.save()
                
                # 2. 更新库存数量
                product_id = transaction_obj.product_id
                quantity = transaction_obj.quantity
                
                if transaction_obj.transaction_type == TransactionType.INBOUND:
                    # 入库操作：增加目标仓库的库存
                    self._update_inventory(
                        product_id, 
                        transaction_obj.to_warehouse_id, 
                        transaction_obj.to_location_id, 
                        quantity,
                        transaction_obj.lot_number,
                        transaction_obj.serial_number
                    )
                elif transaction_obj.transaction_type == TransactionType.OUTBOUND:
                    # 出库操作：减少源仓库的库存
                    self._update_inventory(
                        product_id, 
                        transaction_obj.from_warehouse_id, 
                        transaction_obj.from_location_id, 
                        -quantity,
                        transaction_obj.lot_number,
                        transaction_obj.serial_number
                    )
                elif transaction_obj.transaction_type == TransactionType.TRANSFER:
                    # 移库操作：减少源仓库库存，增加目标仓库库存
                    self._update_inventory(
                        product_id, 
                        transaction_obj.from_warehouse_id, 
                        transaction_obj.from_location_id, 
                        -quantity,
                        transaction_obj.lot_number,
                        transaction_obj.serial_number
                    )
                    self._update_inventory(
                        product_id, 
                        transaction_obj.to_warehouse_id, 
                        transaction_obj.to_location_id, 
                        quantity,
                        transaction_obj.lot_number,
                        transaction_obj.serial_number
                    )
                
                # 3. 返回创建结果和更新后的库存信息
                updated_inventory = Inventory.objects.filter(
                    product_id=product_id, 
                    warehouse_id__in=[
                        transaction_obj.from_warehouse_id, 
                        transaction_obj.to_warehouse_id
                    ]
                ).exclude(is_deleted=True)
                
                inventory_serializer = InventorySerializer(updated_inventory, many=True)
                
                return Response({
                    'transaction': serializer.data,
                    'inventory': inventory_serializer.data
                }, status=status.HTTP_201_CREATED)
        except Exception as e:
            return Response({
                'code': status.HTTP_400_BAD_REQUEST,
                'message': f'创建交易失败：{str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    def _update_inventory(self, product_id, warehouse_id, location_id, quantity, lot_number=None, serial_number=None):
        """
        更新库存数量的内部方法
        
        Args:
            product_id: 产品ID
            warehouse_id: 仓库ID
            location_id: 库位ID
            quantity: 变动数量
            lot_number: 批次号（可选）
            serial_number: 序列号（可选）
        """
        # 构建查询条件
        filters = {
            'product_id': product_id,
            'warehouse_id': warehouse_id,
            'location_id': location_id,
            'is_deleted': False
        }
        
        # 如果提供了批次号，添加到查询条件
        if lot_number is not None:
            filters['lot_number'] = lot_number
        
        # 如果提供了序列号，添加到查询条件
        if serial_number is not None:
            filters['serial_number'] = serial_number
        
        # 查找或创建库存记录
        inventory, created = Inventory.objects.get_or_create(
            defaults={'quantity': 0, 'available_quantity': 0, 'reserved_quantity': 0},
            **filters
        )
        
        # 更新库存数量
        inventory.quantity += quantity
        inventory.available_quantity += quantity
        inventory.save()